﻿using System;
using nRoute.Components.Composition;
using nRoute.Internal;

namespace nRoute.ViewServices
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true, Inherited = false)]
    public class MapViewServiceAttribute
		 : MapResourceBaseAttribute
    {
        private const string MUSTBE_VIEWSERVICE_TYPE = "{0} type must be an implementation of {1}.";

        private readonly Type _viewServiceType;
        private readonly string _name;

        public MapViewServiceAttribute(Type viewServiceType)
		    : this(viewServiceType, null) { }

        public MapViewServiceAttribute(Type viewServiceType, string name)
        {   
            Guard.ArgumentNotNull(viewServiceType, "viewServiceType");
            
            // save
            _viewServiceType = viewServiceType;
            _name = name;
            Lifetime = ViewServiceLifetime.Singleton;
            InitializationMode = InitializationMode.OnDemand;
        }

#region Properties

        public ViewServiceLifetime Lifetime { get; set; }

        public InitializationMode InitializationMode { get; set; }

        public bool IsDefault { get; set; }

#endregion

#region Overrides

        protected internal override bool IsDefaultResource
        {
            get { return IsDefault; }
        }

        protected internal override bool CanInitialize(Type targetType)
        {
             return true;
        }

        protected internal override Type GetResourceType(Type targetType)
        {
            return _viewServiceType;
        }

        protected internal override IResourceLocator GetResourceLocator(Type targetType)
        {
            EnsureIsViewServiceType(targetType, _viewServiceType);
            return new DefaultViewServiceLocator(new ViewServiceMeta(_viewServiceType, targetType, _name, 
                InitializationMode,Lifetime));
        }

#endregion

#region Helpers

        protected static void EnsureIsViewServiceType(Type implementationType, Type viewServiceType)
        {
            if (!viewServiceType.IsAssignableFrom(implementationType)) throw new InvalidOperationException(
                string.Format(MUSTBE_VIEWSERVICE_TYPE, implementationType.FullName, viewServiceType.FullName));
        }

#endregion

    }
}
